﻿using Core.Infrastructure;
using Finbuckle.MultiTenant;
using Infrastructure.Mvc.Routing;
using Microsoft.AspNetCore.Builder;

namespace Infrastructure.Extensions;

/// <summary>
/// Represents extensions of IApplicationBuilder
/// </summary>
public static class ApplicationBuilderExtensions
{
    /// <summary>
    /// Configure the application HTTP request pipeline
    /// </summary>
    /// <param name="application">Builder for configuring an application's request pipeline</param>
    public static void ConfigureRequestPipeline(this IApplicationBuilder application)
    {
        EngineContext.Current.ConfigureRequestPipeline(application);
    }

    ///// <summary>
    ///// Publish AppStarted event
    ///// </summary>
    ///// <param name="_">Builder for configuring an application's request pipeline</param>
    ///// <returns>A task that represents the asynchronous operation</returns>
    //public static async Task PublishAppStartedEventAsync(this IApplicationBuilder _)
    //{
    //    ////publish AppStartedEvent
    //    //var eventPublisher = EngineContext.Current.Resolve<IEventPublisher>();
    //    //await eventPublisher.PublishAsync(new AppStartedEvent());

    //}

    ///// <summary>
    ///// Add exception handling
    ///// </summary>
    ///// <param name="application">Builder for configuring an application's request pipeline</param>
    //public static void UseNopExceptionHandler(this IApplicationBuilder application)
    //{
    //    var appSettings = EngineContext.Current.Resolve<AppSettings>();
    //    var webHostEnvironment = EngineContext.Current.Resolve<IWebHostEnvironment>();
    //    var useDetailedExceptionPage = appSettings.Get<CommonConfig>().DisplayFullErrorStack || webHostEnvironment.IsDevelopment();
    //    if (useDetailedExceptionPage)
    //    {
    //        //get detailed exceptions for developing and testing purposes
    //        application.UseDeveloperExceptionPage();
    //    }
    //    else
    //    {
    //        //or use special exception handler
    //        application.UseExceptionHandler("/Error/Error");
    //    }

    //    //log errors
    //    application.UseExceptionHandler(handler =>
    //    {
    //        handler.Run(async context =>
    //        {
    //            var exception = context.Features.Get<IExceptionHandlerFeature>()?.Error;
    //            if (exception == null)
    //                return;

    //            try
    //            {
    //                //check whether database is installed
    //                if (DataSettingsManager.IsDatabaseInstalled())
    //                {
    //                    //get current customer
    //                    var currentCustomer = await EngineContext.Current.Resolve<IWorkContext>().GetCurrentCustomerAsync();

    //                    //log error
    //                    await EngineContext.Current.Resolve<ILogger>().ErrorAsync(exception.Message, exception, currentCustomer);
    //                }
    //            }
    //            finally
    //            {
    //                //rethrow the exception to show the error page
    //                ExceptionDispatchInfo.Throw(exception);
    //            }
    //        });
    //    });
    //}

    /// <summary>
    /// Adds a special handler that checks for responses with the 400 status code (bad request)
    /// </summary>
    /// <param name="application">Builder for configuring an application's request pipeline</param>
    public static void UseBadRequestResult(this IApplicationBuilder application)
    {
        //application.UseStatusCodePages(async context =>
        //{
        //    //handle 404 (Bad request)
        //    if (context.HttpContext.Response.StatusCode == StatusCodes.Status400BadRequest)
        //    {
        //        var logger = EngineContext.Current.Resolve<ILogger>();
        //        var workContext = EngineContext.Current.Resolve<IWorkContext>();
        //        await logger.ErrorAsync("Error 400. Bad request", null, customer: await workContext.GetCurrentCustomerAsync());
        //    }
        //});
    }

    ///// <summary>
    ///// Configure middleware for dynamically compressing HTTP responses
    ///// </summary>
    ///// <param name="application">Builder for configuring an application's request pipeline</param>
    //public static void UseNopResponseCompression(this IApplicationBuilder application)
    //{
    //    if (!DataSettingsManager.IsDatabaseInstalled())
    //        return;

    //    //whether to use compression (gzip by default)
    //    if (EngineContext.Current.Resolve<CommonSettings>().UseResponseCompression)
    //        application.UseResponseCompression();
    //}

    /// <summary>
    /// Configure static file serving
    /// </summary>
    /// <param name="application">Builder for configuring an application's request pipeline</param>
    public static void UseBoilerplateStaticFiles(this IApplicationBuilder application)
    {
        //plugins static files
        application.UseStaticFiles();
    }

    /// <summary>
    /// Adds the authentication middleware, which enables authentication capabilities.
    /// </summary>
    /// <param name="application">Builder for configuring an application's request pipeline</param>
    public static void UseBoilerplateAuthentication(this IApplicationBuilder application)
    {
        ////check whether database is installed
        //if (!DataSettingsManager.IsDatabaseInstalled())
        //    return;

        //application.UseMiddleware<AuthenticationMiddleware>();
    }

    /// <summary>
    /// Configure Endpoints routing
    /// </summary>
    /// <param name="application">Builder for configuring an application's request pipeline</param>
    public static void UseBoilerplateEndpoints(this IApplicationBuilder application)
    {
        //Execute the endpoint selected by the routing middleware
        application.UseEndpoints(endpoints =>
        {
            //register all routes
            EngineContext.Current.Resolve<IRoutePublisher>().RegisterRoutes(endpoints);
        });
    }
}
